using OfficeOpenXml;
using OfficeOpenXml.Style;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using 请求响应加密.attr;

namespace 请求响应加密.Tools.Excel
{
    public static class ExcelHelper
    {
        private static byte[] ExportToExcel<T>(List<T> data)
        {
            if (data == null || !data.Any())
                throw new ArgumentException("数据为空，无法导出");

            var type = typeof(T);
            var sheetAttr = type.GetCustomAttribute<ExcelSheetAttribute>() ??
                            new ExcelSheetAttribute("Sheet1");

            var properties = type.GetProperties()
                .Where(p => p.GetCustomAttribute<ExcelCellAttribute>() != null)
                .ToList();

            ExcelPackage.LicenseContext = OfficeOpenXml.LicenseContext.NonCommercial;
            using var package = new ExcelPackage();
            var sheet = package.Workbook.Worksheets.Add(sheetAttr.SheetName);

            int startRow = sheetAttr.StartRow == 0 ? 1 : sheetAttr.StartRow;
            int colIndex = 1;
            int rowCount = data.Count;

            // 写入表头
            if (sheetAttr.ShowColumnHeader)
            {
                rowCount += startRow;
                foreach (var prop in properties)
                {
                    var attr = prop.GetCustomAttribute<ExcelCellAttribute>();
                    var header = attr?.CellName ?? prop.Name;

                    sheet.Cells[startRow, colIndex].Value = header;
                    sheet.Cells[startRow, colIndex].Style.Font.Bold = true;
                    sheet.Cells[startRow, colIndex].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;

                    string startAddrStr = GetCharCode(colIndex - 1) + (startRow + 1).ToString();
                    string endAddrStr = GetCharCode(colIndex - 1) + rowCount.ToString();
                    var cellRange = sheet.Cells[$"{startAddrStr}:{endAddrStr}"];

                    if (attr != null)
                    {
                        // 字体样式
                        cellRange.Style.Font.Name = attr.FontName;
                        cellRange.Style.Font.Size = attr.FontSize;
                        cellRange.Style.Font.Bold = attr.FontBold;
                        cellRange.Style.Font.Italic = attr.FontItalic;
                        cellRange.Style.Font.UnderLine = attr.UnderLine;
                        if (!string.IsNullOrEmpty(attr.FontColor))
                        {
                            var fontColor = Color.FromName(attr.FontColor);
                            if (fontColor.IsKnownColor)
                                cellRange.Style.Font.Color.SetColor(fontColor);
                        }

                        // 单元格样式
                        cellRange.Style.Indent = attr.Indent;
                        cellRange.Style.WrapText = attr.WrapText;
                        cellRange.Style.TextRotation = attr.TextRotation;

                        // 边框
                        if (!string.IsNullOrEmpty(attr.BorderStyle))
                        {
                            var borderStyle = (ExcelBorderStyle)Enum.Parse(typeof(ExcelBorderStyle), attr.BorderStyle);
                            var borders = cellRange.Style.Border;
                            var parts = attr.Border.Split(',');
                            if (parts.Length == 4)
                            {
                                if (parts[0] == "1") borders.Top.Style = borderStyle;
                                if (parts[1] == "1") borders.Left.Style = borderStyle;
                                if (parts[2] == "1") borders.Bottom.Style = borderStyle;
                                if (parts[3] == "1") borders.Right.Style = borderStyle;
                            }
                        }

                        // 背景色
                        if (!string.IsNullOrEmpty(attr.BackgroundColor))
                        {
                            var bgColor = Color.FromName(attr.BackgroundColor);
                            if (bgColor.IsKnownColor)
                            {
                                cellRange.Style.Fill.PatternType = (ExcelFillStyle)Enum.Parse(typeof(ExcelFillStyle), attr.BackgroundStyle);
                                cellRange.Style.Fill.BackgroundColor.SetColor(bgColor);
                            }
                        }
                    }

                    colIndex++;
                }
                startRow++;
            }

            // 写入数据
            for (int i = 0; i < data.Count; i++)
            {
                var item = data[i];
                for (int j = 0; j < properties.Count; j++)
                {
                    var value = properties[j].GetValue(item);
                    sheet.Cells[startRow + i, j + 1].Value = value?.ToString();
                }
            }

            // 自动列宽（加上最大宽度限制）
            sheet.Cells[sheet.Dimension.Address].AutoFitColumns(2, 50);

            // 合并相邻相同内容的单元格
            for (int col = 1; col <= properties.Count; col++)
            {
                var prop = properties[col - 1];
                var attr = prop.GetCustomAttribute<ExcelCellAttribute>();
                if (attr == null || !attr.MergeSameCells)
                    continue;

                int mergeStartRow = startRow;
                string? lastValue = sheet.Cells[startRow, col].Text;

                for (int row = startRow + 1; row <= startRow + data.Count; row++)
                {
                    // 到达最后一行或值发生变化时触发合并
                    bool isLastRow = row == startRow + data.Count;
                    string currentValue = isLastRow ? null : sheet.Cells[row, col].Text;

                    if (isLastRow || !string.Equals(currentValue, lastValue))
                    {
                        if (row - 1 > mergeStartRow)
                        {
                            sheet.Cells[mergeStartRow, col, row - 1, col].Merge = true;
                            var cellRange = sheet.Cells[mergeStartRow, col];
                            cellRange.Style.VerticalAlignment = ExcelVerticalAlignment.Center;
                            // 边框
                            if (!string.IsNullOrEmpty(attr.BorderStyle))
                            {
                                var borderStyle = (ExcelBorderStyle)Enum.Parse(typeof(ExcelBorderStyle), attr.BorderStyle);
                                var borders = cellRange.Style.Border;
                                var parts = attr.Border.Split(',');
                                if (parts.Length == 1)
                                {
                                    borders.Top.Style = borderStyle;
                                    borders.Left.Style = borderStyle;
                                    borders.Bottom.Style = borderStyle;
                                    borders.Right.Style = borderStyle;
                                }
                                if (parts.Length == 4)
                                {
                                    if (parts[0] == "1") borders.Top.Style = borderStyle;
                                    if (parts[1] == "1") borders.Left.Style = borderStyle;
                                    if (parts[2] == "1") borders.Bottom.Style = borderStyle;
                                    if (parts[3] == "1") borders.Right.Style = borderStyle;
                                }
                            }

                            mergeStartRow = row;
                            lastValue = currentValue;
                        }
                    }
                }
            }

            return package.GetAsByteArray();
        }


        private static byte[] ExportToExcelWithoutAttr<T>(List<T> data)
        {
            if (data == null || !data.Any())
                throw new ArgumentException("数据为空，无法导出");

            var type = typeof(T);
            var sheetName = type.Name;

            var properties = type.GetProperties().ToList();
            // 处理证书，避免报错提示
            ExcelPackage.LicenseContext = LicenseContext.NonCommercial;

            using var package = new ExcelPackage();
            var sheet = package.Workbook.Worksheets.Add(sheetName);

            int startRow = 1;
            int colIndex = 1;
            int rowCount = data.Count();

            rowCount += startRow;
            foreach (var prop in properties)
            {
                var header = prop.Name;
                sheet.Cells[startRow, colIndex].Value = header;
                sheet.Cells[startRow, colIndex].Style.Font.Bold = true;
                sheet.Cells[startRow, colIndex].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;

                string startAddrStr = GetCharCode(colIndex - 1) + (startRow + 1).ToString();
                string endAddrStr = GetCharCode(colIndex - 1) + rowCount.ToString();

                colIndex++;
            }
            startRow++; // 数据从下一行开始

            // 写入数据
            for (int i = 0; i < data.Count; i++)
            {
                var item = data[i];
                for (int j = 0; j < properties.Count; j++)
                {
                    var value = properties[j].GetValue(item);
                    sheet.Cells[startRow + i, j + 1].Value = value;
                }
            }

            sheet.Cells[sheet.Dimension.Address].AutoFitColumns();
            return package.GetAsByteArray();
        }

        // 可选：保存为文件
        public static void SaveToFile<T>(List<T> data, string filePath, bool useAttr = true)
        {
            if (data == null || data.Count == 0) return;

            FileInfo fileInfo = new FileInfo(filePath);
            string extension = fileInfo.Extension;
            string[] extNames = new string[] { ".xlsx", "xls" };
            if (!extNames.Contains(extension))
                throw new Exception("文件扩展名错误，请检查扩展名");
            var bytes = useAttr ? ExportToExcel(data) : ExportToExcelWithoutAttr(data);
            File.WriteAllBytes(filePath, bytes);
        }

        private static char GetCharCode(int idx)
        {
            return (char)('A' + idx);
        }
    }

}
